{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "input_size = 1\n",
    "output_size = 1\n",
    "hidden_size = 16\n",
    "num_time_step = 50\n",
    "lr = 0.01"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class Net(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Net,self).__init__()\n",
    "        self.net = nn.RNN(\n",
    "            input_size=input_size,\n",
    "            hidden_size = hidden_size,\n",
    "            num_layers = 1,\n",
    "            batch_first = True#转换为（batch，seq_len，emb_size）\n",
    "        )\n",
    "        for p in self.net.parameters():\n",
    "            nn.init.normal_(p,mean=0.0,std=0.001)\n",
    "        self.linear = nn.Linear(hidden_size,output_size)\n",
    "    def forward(self,x,hidden_prev):\n",
    "        out,hidden_prev = self.net(x,hidden_prev)#out（batch，hidden_size,embed_size）\n",
    "        out = out.view(-1,hidden_size)\n",
    "        out = self.linear(out)\n",
    "        out = out.unsqueeze(dim=0)\n",
    "        return out,hidden_prev"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch:0,loss:0.5257904529571533\n",
      "epoch:1000,loss:0.0012203371152281761\n",
      "epoch:2000,loss:0.0008573596132919192\n",
      "epoch:3000,loss:0.0007693944498896599\n",
      "epoch:4000,loss:0.0002501471317373216\n",
      "epoch:5000,loss:0.0001314039691351354\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "model = Net()\n",
    "criterion = nn.MSELoss()\n",
    "optimizer = optim.Adam(model.parameters(),lr)\n",
    "hidden_prev = torch.zeros(1,1,hidden_size)\n",
    "for epoch in range(6000):\n",
    "    start = np.random.randint(3,size=1)[0]#产生一个0-3的随机数\n",
    "    time_steps = np.linspace(start,start+10,num_time_step)\n",
    "    data = np.sin(time_steps)\n",
    "    data = data.reshape(num_time_step,1)\n",
    "    \n",
    "    x = torch.Tensor(data[:-1]).float().view(1,num_time_step-1,1)\n",
    "    y = torch.Tensor(data[1:]).float().view(1,num_time_step-1,1)\n",
    "    \n",
    "    out,hidden_prev = model(x,hidden_prev)\n",
    "    loss = criterion(out,y)\n",
    "    hidden_prev = hidden_prev.detach()\n",
    "    model.zero_grad()\n",
    "    loss.backward()\n",
    "    optimizer.step()\n",
    "    \n",
    "    if epoch % 1000 == 0 :\n",
    "        print('epoch:{},loss:{}'.format(epoch,loss))\n",
    "        \n",
    "start = np.random.randint(3,size=1)[0]#产生一个0-3的随机数\n",
    "time_steps = np.linspace(start,start+10,num_time_step)\n",
    "data = np.sin(time_steps)\n",
    "data = data.reshape(num_time_step,1)\n",
    "x = torch.tensor(data[:-1]).float().view(1,num_time_step-1,1)\n",
    "y = torch.tensor(data[1:]).float().view(1,num_time_step-1,1)\n",
    "\n",
    "predictions = []\n",
    "input = x[:,0,:]\n",
    "for _ in range(x.shape[1]):\n",
    "    input = input.view(1,1,1)\n",
    "    (pred,hidden_prev) = model(input,hidden_prev)\n",
    "    input = pred\n",
    "    predictions.append(pred.detach().numpy().ravel()[0])\n",
    "    \n",
    "x = x.data.numpy().ravel()\n",
    "y = y.data.numpy()\n",
    "plt.scatter(time_steps[:-1], x.ravel(), s=90)\n",
    "plt.plot(time_steps[:-1], x.ravel())\n",
    "\n",
    "plt.scatter(time_steps[1:], predictions)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 0 loss 0.5526787042617798\n",
      "Iteration: 1000 loss 0.000330829294398427\n",
      "Iteration: 2000 loss 0.0009250730508938432\n",
      "Iteration: 3000 loss 0.00023615482496097684\n",
      "Iteration: 4000 loss 0.00017761631170287728\n",
      "Iteration: 5000 loss 0.00037565617822110653\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import  numpy as np\n",
    "import  torch\n",
    "import  torch.nn as nn\n",
    "import  torch.optim as optim\n",
    "from    matplotlib import pyplot as plt\n",
    "\n",
    "\n",
    "num_time_steps = 50\n",
    "input_size = 1\n",
    "hidden_size = 16\n",
    "output_size = 1\n",
    "lr=0.01\n",
    "\n",
    "\n",
    "\n",
    "class Net(nn.Module):\n",
    "\n",
    "    def __init__(self, ):\n",
    "        super(Net, self).__init__()\n",
    "\n",
    "        self.rnn = nn.RNN(\n",
    "            input_size=input_size,\n",
    "            hidden_size=hidden_size,\n",
    "            num_layers=1,\n",
    "            batch_first=True,\n",
    "        )\n",
    "        for p in self.rnn.parameters():\n",
    "          nn.init.normal_(p, mean=0.0, std=0.001)\n",
    "\n",
    "        self.linear = nn.Linear(hidden_size, output_size)\n",
    "\n",
    "    def forward(self, x, hidden_prev):\n",
    "\n",
    "       out, hidden_prev = self.rnn(x, hidden_prev)\n",
    "       # [b, seq, h]\n",
    "       out = out.view(-1, hidden_size)\n",
    "       out = self.linear(out)\n",
    "       out = out.unsqueeze(dim=0)\n",
    "       return out, hidden_prev\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "model = Net()\n",
    "criterion = nn.MSELoss()\n",
    "optimizer = optim.Adam(model.parameters(), lr)\n",
    "\n",
    "hidden_prev = torch.zeros(1, 1, hidden_size)\n",
    "\n",
    "for iter in range(6000):\n",
    "    start = np.random.randint(3, size=1)[0]\n",
    "    time_steps = np.linspace(start, start + 10, num_time_steps)\n",
    "    data = np.sin(time_steps)\n",
    "    data = data.reshape(num_time_steps, 1)\n",
    "    x = torch.tensor(data[:-1]).float().view(1, num_time_steps - 1, 1)\n",
    "    y = torch.tensor(data[1:]).float().view(1, num_time_steps - 1, 1)\n",
    "\n",
    "    output, hidden_prev = model(x, hidden_prev)\n",
    "    hidden_prev = hidden_prev.detach()\n",
    "\n",
    "    loss = criterion(output, y)\n",
    "    model.zero_grad()\n",
    "    loss.backward()\n",
    "    # for p in model.parameters():\n",
    "    #     print(p.grad.norm())\n",
    "    # torch.nn.utils.clip_grad_norm_(p, 10)\n",
    "    optimizer.step()\n",
    "\n",
    "    if iter % 1000 == 0:\n",
    "        print(\"Iteration: {} loss {}\".format(iter, loss.item()))\n",
    "\n",
    "start = np.random.randint(3, size=1)[0]\n",
    "time_steps = np.linspace(start, start + 10, num_time_steps)\n",
    "data = np.sin(time_steps)\n",
    "data = data.reshape(num_time_steps, 1)\n",
    "x = torch.tensor(data[:-1]).float().view(1, num_time_steps - 1, 1)\n",
    "y = torch.tensor(data[1:]).float().view(1, num_time_steps - 1, 1)\n",
    "\n",
    "predictions = []\n",
    "input = x[:, 0, :]\n",
    "for _ in range(x.shape[1]):\n",
    "    input = input.view(1, 1, 1)\n",
    "    (pred, hidden_prev) = model(input, hidden_prev)\n",
    "    input = pred\n",
    "    predictions.append(pred.detach().numpy().ravel()[0])\n",
    "\n",
    "x = x.data.numpy().ravel()\n",
    "y = y.data.numpy()\n",
    "plt.scatter(time_steps[:-1], x.ravel(), s=90)\n",
    "plt.plot(time_steps[:-1], x.ravel())\n",
    "\n",
    "plt.scatter(time_steps[1:], predictions)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
